Accumulator.java
package org.codefilarete.stalactite.sql.result;
import java.sql.ResultSet;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.function.Supplier;
import org.codefilarete.stalactite.sql.result.Accumulators.AccumulatorSupport;
/**
* Contract to build result of the {@link WholeResultSetTransformer#transformAll(ResultSet, Accumulator)}.
* Can be seen as a light version of Java Collector, here are main differences :
* - since its usage is aimed at {@link ResultSet} consumption, there's no need to take parallel iteration into account
* - it's not expected to address very wide usages as Stream would require
*
* A set of pre-defined {@link Accumulator}s is defined in the {@link Accumulators} class.
*
* @param <T> the type of elements to be collected
* @param <S> the type of the seed that collects elements
* @param <R> the type of the result
* @author Guillaume Mary
* @see Accumulators
*/
public interface Accumulator<T, S, R> {
/**
* Should return a factory that build the "collector" that will be given to accumulator.
*/
Supplier<S> supplier();
/**
* Should return the accumulator that consumes the "collector" and each bean found on row.
* The result of this method is invoked for each row found in the {@link ResultSet}.
* Input may be an instance that was already previously consumed if row key matches an already consumed one.
*/
BiConsumer<S, T> aggregator();
/**
* Made to return a function that eventually rework initial seed and return the final result.
*/
Function<S, R> finisher();
default <RR> Accumulator<T, S, RR> andThen(Function<R, RR> nextFunction) {
return new AccumulatorSupport<>(supplier(), aggregator(), finisher().andThen(nextFunction));
}
/**
* Iterates over given input and, foreach element, calls {@link #aggregator()} with element and seed (provided by
* {@link #supplier()}), and finally, invokes {@link #finisher()} for returned result arrangement.
*
* @param input elements to be iterated over
* @return result of above described process
*/
default R collect(Iterable<T> input) {
S seed = supplier().get();
BiConsumer<S, T> aggregator = aggregator();
input.forEach(c -> aggregator.accept(seed, c));
Function<S, R> finisher = finisher();
return finisher.apply(seed);
}
}